﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Gota.Common.Annotations;
using System.Xml;
using Gota.Common.Entities.UI;
using Gota.Common.Context;

namespace Gota.Common
{
    public static class AnnotationUtil
    {
        public static List<Annotation> GetAnnotationTree(string xml)
        {
            if (String.IsNullOrEmpty(xml))
            {
                return null;
            }
            XmlDocument annotations = new XmlDocument();
            annotations.LoadXml(xml);
            var annotationNode = annotations.SelectSingleNode("/Annotations");

            return parseAnnotations(annotationNode.ChildNodes);
        }

        public static List<Annotation> GetAnnotationTypeSamples(string xml)
        {
            List<Annotation> retList = new List<Annotation>();
            var annotationTree = GetAnnotationTree(xml);
            distinctAnnotations(annotationTree, retList);
            return retList;
        }

        public static List<Annotation> GetVerticalAnnotationList(string xml)
        {
            List<Annotation> retList = new List<Annotation>();
            var annotationTree = GetAnnotationTree(xml);
            verticalAnnotations(annotationTree, retList);
            return retList;
        }

        private static void verticalAnnotations(List<Annotation> input, List<Annotation> generation)
        {
            foreach (var item in input)
            {
                generation.Add(item);
                distinctAnnotations(item.ChildAnnotations, generation);
            }
        }

        private static void distinctAnnotations(List<Annotation> input, List<Annotation> generation)
        {
            foreach (var item in input)
            {
                if (generation.Where(o => o.Name == item.Name).FirstOrDefault() == null)
                {
                    generation.Add(item);
                }
                distinctAnnotations(item.ChildAnnotations, generation);
            }
        }

        private static List<Annotation> parseAnnotations(XmlNodeList nodeList)
        {
            List<Annotation> retList = new List<Annotation>();

            if (nodeList == null
                || nodeList.Count == 0)
            {
                return retList;
            }

            foreach (XmlNode node in nodeList)
            {
                if (node.NodeType != XmlNodeType.Element)
                {
                    continue;
                }
                Annotation annotation = new Annotation();
                annotation.Name = node.Name;

                foreach (XmlAttribute attribute in node.Attributes)
                {
                    if (attribute.Name.Contains("gateId"))
                    {
                        annotation.Id = int.Parse(attribute.Value);
                    }
                    else
                    {
                        NameValueEntity propertyEntity = new NameValueEntity
                        {
                            Name = attribute.Name,
                            Value = attribute.Value
                        };
                        annotation.Attributes.Add(propertyEntity);
                    }
                }

                retList.Add(annotation);

                annotation.ChildAnnotations.AddRange(parseAnnotations(node.ChildNodes));

                StringBuilder sb = new StringBuilder();
                var stringAttribute = annotation.Attributes.Where(o => o.Name.Equals("string", StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
                if (stringAttribute != null)
                {
                    sb.Append(stringAttribute.Value);
                }
                else if (node.ChildNodes != null
                    && node.ChildNodes.Count > 0
                    && node.FirstChild.NodeType == XmlNodeType.Text)
                {
                    sb.Append(node.FirstChild.Value);
                }
                else
                {
                    foreach (var chAnnotation in annotation.ChildAnnotations)
                    {
                        sb.Append(chAnnotation.ContentText);
                    }
                }
                annotation.ContentText = sb.ToString();
            }
            return retList;
        }
    }
}
